

import 'dart:typed_data';

import 'package:dartx/dartx.dart';
import 'package:flutter_ns_ble/src/extensions.dart';

final _decodeMap = {
  "1100": 1,
  "11101": 2,
  "1101": 3,
  "100": 4,
  "0": 5,
  "101": 6,
  "11100": 7,
  "111100": 8,
  "1111100": 9,
  "1111101": 10,
  "11111100": 11,
  "11111101": 12,
  "111111100": 13,
  "1111111101": 14,
  "11111111100": 15,
  "11111111101": 16,
};
/// 压缩算法，动态心电先用上
class CompressionAlgorithm {
  static List<int> compress(List<int> ecgData) {
    List<int> results = List.empty(growable: true);
    int previous = ecgData.first;
    results.add(previous);
    for (int i = 1; i < ecgData.length; i++) {
      int value = ecgData[i] - previous;
      results.add(value);
      previous = ecgData[i];
    }
    String text = "";
    for (int i in results) {
      text += i >= 0 ? "0" : "1";
      text += i.toRadixString(2).replaceAll("-", "");
    }
    final characters = text.characters.chunked(8);
    List<int> hex = List.empty(growable: true);
    for (var value in characters) {
      hex.add(int.tryParse(value.joinToString(separator: ""), radix: 2) ?? 0);
    }
    print(hex.map((value) => value.toRadixString(16)));
    return results;
  }

  /// 帧序号[3]+心电数据条数[1]+心电数据位数[2]+编码数据位数[2]+心电数据[N]+编码数据[M]，N、M由心电数据数及编码数据数确定；
  List<int> decompress(List<int> data) {
    int index = Uint8List.fromList(data.take(3).toList()).getInt24();
    data = data.drop(3);
    int ecgDataCount = data.take(1).first;
    data = data.drop(1);
    int ecgDataBitsCount =
        Uint8List.fromList(data.take(2).toList()).getUint16() * 2;
    // print("ecgDataBitsCount:${data.take(2).toList().toHex()},$ecgDataBitsCount");
    data = data.drop(2);
    int codeDataBitsCount =
        Uint8List.fromList(data.take(2).toList()).getUint16() * 2;
    // print("codeDataBitsCount:${data.take(2).toList().toHex()},$codeDataBitsCount");
    data = data.drop(2);
    List<int> ecgData = data.take(ecgDataBitsCount).toList();
    // print("ecgData:${ecgData.toHex()}");
    data = data.drop(ecgDataBitsCount);
    List<int> codeData = data.take(codeDataBitsCount).toList();
    // print("codeData:${codeData.toHex()}");

    final codeLengthList = decodeCode(codeData);

    final ecgDataArray = ecgData.chunked(2).toList().drop(1);
    int pre = Uint8List.fromList(ecgData).getInt16();
    String ecgDataBinaryText = "";
    for (var hex in ecgDataArray) {
      ecgDataBinaryText += hex[1].toRadixString(2).padLeft(8, '0') +
          hex[0].toRadixString(2).padLeft(8, '0');
    }
    print("ecgDataBinaryText:$ecgDataBinaryText");
    List<int> ecgDataResults = List.empty(growable: true);
    ecgDataResults.add(pre);
    for (int codeLength in codeLengthList) {
      final characters = ecgDataBinaryText.characters.take(codeLength);
      print("codeLength:$codeLength,characters:${characters}");
      if (codeLength == 1) {
        // 跟上一个数值相同
      } else {
        final binary = characters.skip(1).join();
        print("binary:$binary");
        var num = int.parse(binary, radix: 2);
        num = characters.first == "0" ? num : 0 - num;
        // print("num:$num, result:${pre + num}");
        pre += num;
      }
      ecgDataResults.add(pre);
      ecgDataBinaryText = ecgDataBinaryText.characters.skip(codeLength).join();
    }
    print("ecgDataCount:${ecgDataCount}");
    return ecgDataResults;
  }

  /// 解码编码数据
  List<int> decodeCode(List<int> data) {
    String binaryText = "";
    List<int> codeLengthList = List.empty(growable: true);
    final List<int> d =
        data.chunked(2).map((v) => [v[1], v[0]]).reduce((a, b) => a + b);
    print("编码数据:${d.toHex()}");
    for (var number in d) {
      binaryText += number.toRadixString(2).padLeft(8, '0');

      bool y = true;
      while (y) {
        y = false;
        for (var map in _decodeMap.entries) {
          if (binaryText.startsWith(map.key)) {
            print("${[
              number
            ].toHex()}==${number.toRadixString(2)}，binaryText:$binaryText,value:${map.value}");
            codeLengthList.add(map.value);
            binaryText = binaryText.removePrefix(map.key);
            // print("binaryText:$binaryText");
            y = true;
          }
        }
        if (!y) {
          return codeLengthList;
        }
      }
    }
    return codeLengthList;
  }
}